<script setup lang="ts" name="GoodsSku">
import { GoodsInfo, ValueType, Spec } from '@/types/goods'
import bwPowerset from '@/utils/bwPowerset'
const props = defineProps<{
  goodsInfo: GoodsInfo
  skuId?: string
}>()
const emit = defineEmits<{
  (e: 'checkedGoods', skuId: string): void
}>()
// 1.点击切换高亮效果
const changeSelected = (sub: ValueType, item: Spec) => {
  if (sub.disabled) return // 如果已经是禁用按钮, 禁止按钮点击切换高亮
  //  如果selected为true 就设置为false
  if (sub.selected) {
    sub.selected = false
  } else {
    // 排他, 干掉所有人
    item.values.forEach((value) => (value.selected = false))
    // 复活我自己
    sub.selected = true
  }
  // 点击的时候也要控制按钮的禁用和启用
  defaultDisabled()
  // 用户选择完整的规格后提交数据 skuId给后端
  const fullArr = orderKey().filter((v) => v)
  // console.log(fullArr, '提交选中的SKUID给父组件')
  // 保证选择了完整的规格
  if (fullArr.length === props.goodsInfo.specs.length) {
    // 从字典中查找对应规格的skuId
    // console.log(fullArr.join('+'))
    const submitSkuId = pathMap[fullArr.join('+')][0]
    // console.log(submitSkuId) // 提交的skuId 给父组件
    emit('checkedGoods', submitSkuId)
  } else {
    emit('checkedGoods', '')
  }
}
// 2. 获取路径字典
const getMap = () => {
  // const obj: any = {}
  const obj: { [key: string]: string[] } = {}
  // 2.1 将有效的sku的情况过滤出来
  const skus = props.goodsInfo.skus.filter((item) => item.inventory > 0)
  // 2.2 求子集 保证求子集的是一个数组
  // 2.2.1 将每一个sku的specs的每一项的valueName收集到一个数组中
  skus.forEach((sku) => {
    const arr = sku.specs.map((spec) => spec.valueName)
    // console.log(arr)
    // 2.2.2 求子集
    const sets = bwPowerset(arr)
    // console.log(sets)
    // 2.3 将数据往路径字典中存
    // 2.3.1 对象的键存的是字符串, 需要遍历sets, 将每一个处理成字符串
    sets.forEach((set) => {
      const key = set.join('+') // 对象要存的键
      // console.log(key)
      // if (obj.hasOwnProperty(key)) {
      if (obj[key]) {
        // 对象中存在key, 追加
        obj[key].push(sku.id)
      } else {
        // 对象中不存在key 新增一个key属性
        obj[key] = [sku.id]
      }
    })
  })
  return obj
}
const pathMap = getMap() // 路径字典
// console.log(pathMap)
// 3. 基于做好的路径字典, 做按钮的默认禁用
const defaultDisabled = () => {
  // console.log(orderKey())
  const arr = orderKey() // ['黑色', '', '10cm']
  props.goodsInfo.specs.forEach((spec, index) => {
    // 每一行规格对象
    spec.values.forEach((btnObj) => {
      const newArr = [...arr] // // ['黑色', '', '10cm']
      newArr[index] = btnObj.name
      // console.log(newArr) // 将这个键处理成字符串去pathMap查找
      const key = newArr.filter((item) => item).join('+')
      // console.log(key)
      // btnObj是每一个按钮对象
      // console.log(btnObj.name)
      // 存在字典中的不禁用, 不存在的禁用
      if (pathMap.hasOwnProperty(key)) {
        btnObj.disabled = false
      } else {
        btnObj.disabled = true
      }
    })
  })
}
defaultDisabled() // 默认禁用某些按钮
/* 刚才做的默认单个按钮禁用, 现在 做的是组合按钮禁用
日本 + 20cm + 黑色  的锅没货 ====> 日本 + 20cm + 黑色  不存在路径字典中
点击按钮的时候 获取到按钮的文本, 组合出来一个key 去路径字典中查找  黑色+30cm+日本  30cm+日本+黑色  日本+黑色+30cm
用户选择商品规格的时候, 有可能不是按着先后顺序点击的, 如果随机记录用户点击的按钮的文本 组合的key 有可能会在路径字典中查不到
所以 保证 不论用户怎么样点击, 得到的永远是一个有顺序的key  颜色+尺寸+产地  [ ,  , ] */
// 4.组合禁用 保证有顺序的key
function orderKey() {
  const arr: string[] = []
  props.goodsInfo.specs.forEach((spec, index) => {
    // 找到被选中的按钮
    const btnObj = spec.values.find((btnObj) => btnObj.selected === true)
    // 将按钮的文本放入数组中对应的位置
    if (btnObj) {
      arr[index] = btnObj.name
    } else {
      arr[index] = ''
    }
  })
  return arr
}
// 5. 默认选中一项sku
const defaultSelected = () => {
  if (!props.skuId) return
  // 5.1 从所有的sku中找到指定的sku
  const sku = props.goodsInfo.skus.find((item) => item.id === props.skuId)
  // 5.2 基于找到的sku 做默认规格按钮的selected
  // console.log(sku)
  if (sku) {
    props.goodsInfo.specs.forEach((spec, index) => {
      spec.values.forEach((btnObj) => {
        // console.log(btnObj.name)
        if (btnObj.name === sku.specs[index].valueName) {
          btnObj.selected = true
        }
      })
    })
  }
}
defaultSelected()
// 6. 默认组合禁用
if (props.skuId) {
  defaultDisabled()
  // 默认子传父一次
  emit('checkedGoods', props.skuId)
}
</script>
<template>
  <div class="goods-sku">
    <!-- selected 类名是标记 选中高亮的类名  disabled 禁用 表示当前无货 -->
    <dl v-for="item in goodsInfo.specs" :key="item.id">
      <dt>{{ item.name }}</dt>
      <dd>
        <template v-for="sub in item.values" :key="sub.name">
          <img
            :src="sub.picture"
            :class="{ selected: sub.selected, disabled: sub.disabled }"
            v-if="sub.picture"
            @click="changeSelected(sub, item)"
          />
          <span
            :class="{ selected: sub.selected, disabled: sub.disabled }"
            v-else
            @click="changeSelected(sub, item)"
            >{{ sub.name }}</span
          >
        </template>
      </dd>
    </dl>
  </div>
</template>

<style scoped lang="less">
.sku-state-mixin () {
  border: 1px solid #e4e4e4;
  margin-right: 10px;
  cursor: pointer;
  &.selected {
    border-color: @xtxColor;
  }
  &.disabled {
    opacity: 0.6;
    border-style: dashed;
    cursor: not-allowed;
  }
}
.goods-sku {
  padding-left: 10px;
  padding-top: 20px;
  dl {
    display: flex;
    padding-bottom: 20px;
    align-items: center;
    dt {
      width: 50px;
      color: #999;
    }
    dd {
      flex: 1;
      color: #666;
      > img {
        width: 50px;
        height: 50px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
      > span {
        display: inline-block;
        height: 30px;
        line-height: 30px;
        padding: 0 20px;
        margin-top: 5px;
        .sku-state-mixin ();
      }
    }
  }
}
</style>
